using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO.BusinessObjectRules
{
    [TestFixture]
    public class TestDMRelationshipMustHaveProperty
    {
        [SetUp]
        public void SetupTest()
        {
            //Runs every time that any testmethod is executed
            TestUtilsDomain.SetupTest();
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //Code that is executed before any test is run in this class. If multiple tests
            // are executed then it will still only be called once.
            TestUtilsDomain.SetupFixture();
        }

        [TearDown]
        public void TearDownTest()
        {
            //runs every time any testmethod is complete
        }

        #region DMRelationshipMustHaveProperty

        [Test]
        public void Test_CreateDMRelationshipMustHavePropertyRule()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            //---------------Test Result -----------------------
            Assert.IsNotNull(rule);
            Assert.AreEqual("DMRelationshipMustHaveProperty", rule.Name);
            Assert.AreEqual(ErrorLevel.Error, rule.ErrorLevel);
        }

        [Test]
        public void Test_CreateDMRelationshipMustHavePropertyRule_NoClassDM()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            relationship.ClassDM = null;
            //---------------Assert Precondition----------------
            Assert.IsNull(relationship.ClassDM);
            //---------------Execute Test ----------------------
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            //---------------Test Result -----------------------
            Assert.IsNotNull(rule);
            Assert.AreEqual("DMRelationshipMustHaveProperty", rule.Name);
            Assert.AreEqual(ErrorLevel.Error, rule.ErrorLevel);
        }

//        [Test]
//        public void Test_CreateDMRelationshipMustHavePropertyRule_WhenRelationshipNull_ShouldRaiseError()
//        {
//            //---------------Set up test pack-------------------
//            //---------------Assert Precondition----------------
//            //---------------Execute Test ----------------------
//            try
//            {
//                new DMRelationshipMustHaveProperty(null);
//                Assert.Fail("expected ArgumentNullException");
//            }
//                //---------------Test Result -----------------------
//            catch (ArgumentNullException ex)
//            {
//                StringAssert.Contains("Value cannot be null", ex.Message);
//                StringAssert.Contains("dmRelationship", ex.ParamName);
//            }
//        }

        [Test]
        public void Test_DMRelationshipMustHaveProperty_WhenNoOwningClass_ShouldFail()
        {
            //---------------Set up test pack-------------------

            DMRelationship dmRelationship = new DMRelationship();
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            dmRelationship.RelationshipProperties.CreateBusinessObject();
            dmRelationship.RelatedClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.IsNull(dmRelationship.OwnerClass);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmRelationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The Relationship '", rule.Message);
            StringAssert.Contains("'" + dmRelationship + "' on Class '" + dmRelationship.ClassDM + "'", rule.Message);
            StringAssert.Contains("' must have at least one Property", rule.Message);
        }

        [Test]
        public void Test_DMRelationshipMustHaveProperty_WhenNoRelatedClass_ShouldFail()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            dmClass.Properties.CreateBusinessObject();
            DMRelationship dmRelationship = dmClass.OwnerRelationships.CreateBusinessObject();
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            dmRelationship.RelationshipProperties.CreateBusinessObject();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.IsNull(dmRelationship.RelatedClass);
            Assert.IsNotNull(dmRelationship.OwnerClass);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmRelationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            TestUtilsShared.AssertStringNotEmpty(rule.Message, "rule.Message");
        }
        [Test]
        public void Test_DMRelationshipMustHaveProperty_FailsIfHasNoProp()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            dmClass.Properties.CreateBusinessObject();
            DMRelationship dmRelationship = dmClass.OwnerRelationships.CreateBusinessObject();
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            dmRelationship.RelatedClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dmRelationship.RelationshipProperties.Count);
            Assert.IsNotNull(dmRelationship.RelatedClass);
            Assert.IsNotNull(dmRelationship.OwnerClass);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmRelationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            TestUtilsShared.AssertStringNotEmpty(rule.Message, "rule.Message");
        }
        
        [Test]
        public void Test_DMRelationshipMustHaveProperty_FailsIfRelationshipDoesNotHaveOwnerProp()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            DMRelationshipProperty dmRelationshipProperty = relationship.RelationshipProperties.CreateBusinessObject();
            DMClass relatedClass =  TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            relationship.RelatedClass = relatedClass;
            DMProperty relatedProp = relatedClass.Properties.CreateBusinessObject();
            dmRelationshipProperty.RelatedProperty = relatedProp;

            //---------------Assert Precondition----------------
            Assert.IsNotNull(relationship.RelatedClass);
            Assert.IsNotNull(relationship.OwnerClass);
            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties = relationship.RelationshipProperties;
            Assert.AreEqual(1, relationshipProperties.Count);
            DMRelationshipProperty relationshipProperty = relationshipProperties[0];
            Assert.IsNull(relationshipProperty.OwnerProperty);
            Assert.IsNotNull(relationshipProperty.RelatedProperty);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(relationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            TestUtilsShared.AssertStringNotEmpty(rule.Message, "rule.Message");
        }
        
        [Test]
        public void Test_DMRelationshipMustHaveProperty_FailsIfRelationshipDoesNotHaveRelatedProp()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            DMRelationshipProperty dmRelationshipProperty = relationship.RelationshipProperties.CreateBusinessObject();
            DMProperty ownerProp = dmClass.Properties.CreateBusinessObject();
            dmRelationshipProperty.OwnerProperty = ownerProp;
            relationship.RelatedClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(relationship.RelatedClass);
            Assert.IsNotNull(relationship.OwnerClass);
            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties = relationship.RelationshipProperties;
            Assert.AreEqual(1, relationshipProperties.Count);
            DMRelationshipProperty relationshipProperty = relationshipProperties[0];
            Assert.IsNotNull(relationshipProperty.OwnerProperty);
            Assert.IsNull(relationshipProperty.RelatedProperty);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(relationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            TestUtilsShared.AssertStringNotEmpty(rule.Message, "rule.Message");
        }

        [Test]
        public void Test_DMRelationshipMustHaveProperty_PassesIfHasOnePropWithBothOwnerAndRelatedProp()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            IBusinessObjectRule rule = new DMRelationshipMustHaveProperty();
            DMRelationshipProperty dmRelationshipProperty = relationship.RelationshipProperties.CreateBusinessObject();
            DMClass relatedClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            relationship.RelatedClass = relatedClass;
            DMProperty relatedProp = relatedClass.Properties.CreateBusinessObject();
            dmRelationshipProperty.RelatedProperty = relatedProp;
            DMProperty ownerProp = dmClass.Properties.CreateBusinessObject();
            dmRelationshipProperty.OwnerProperty = ownerProp;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(relationship.RelatedClass);
            Assert.IsNotNull(relationship.OwnerClass);
            BusinessObjectCollection<DMRelationshipProperty> relationshipProperties = relationship.RelationshipProperties;
            Assert.AreEqual(1, relationshipProperties.Count);
            DMRelationshipProperty relationshipProperty = relationshipProperties[0];
            Assert.IsNotNull(relationshipProperty.OwnerProperty);
            Assert.IsNotNull(relationshipProperty.RelatedProperty);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(relationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        } 

        #endregion
    }
}